\subsubsection{ARM: \OptimizingKeilVI (\ARMMode)}
\label{sec:SwitchARMLot}

\lstinputlisting[caption=\OptimizingKeilVI (\ARMMode),style=customasmARM]{patterns/08_switch/2_lot/lot_ARM_ARM_O3.asm}

В этом коде используется та особенность режима ARM, 
что все инструкции в этом режиме имеют фиксированную длину 4 байта.

Итак, не будем забывать, что максимальное значение для $a$ это 4: всё что выше, должно вызвать
вывод строки \IT{<<something unknown\textbackslash{}n>>}.

\myindex{ARM!\Instructions!CMP}
\myindex{ARM!\Instructions!ADDCC}
Самая первая инструкция \TT{CMP R0, \#5} сравнивает входное значение в $a$ c 5.

\footnote{ADD---складывание чисел}
Следующая инструкция \TT{ADDCC PC, PC, R0,LSL\#2} сработает только в случае если $R0 < 5$ (\IT{CC=Carry clear / Less than}). 
Следовательно, если \TT{ADDCC} не сработает (это случай с $R0 \geq 5$), выполнится переход на метку 
\IT{default\_case}.

Но если $R0 < 5$ и \TT{ADDCC} сработает, то произойдет следующее.

Значение в \Reg{0} умножается на 4.
Фактически, \TT{LSL\#2} в суффиксе инструкции означает \q{сдвиг влево на 2 бита}.

Но как будет видно позже~(\myref{division_by_shifting}) в секции \q{\ShiftsSectionName}, 
сдвиг влево на 2 бита, это эквивалентно его умножению на 4.

Затем полученное $R0*4$ прибавляется к текущему значению \ac{PC}, 
совершая, таким образом, переход на одну из расположенных ниже инструкций \TT{B} (\IT{Branch}).

На момент исполнения \TT{ADDCC},
содержимое \ac{PC} на 8 байт больше (\TT{0x180}), чем адрес по которому расположена сама инструкция \TT{ADDCC} (\TT{0x178}), 
либо, говоря иным языком, на 2 инструкции больше.

\myindex{ARM!Конвейер}
Это связано с работой конвейера процессора ARM:
пока исполняется инструкция \TT{ADDCC}, процессор уже начинает обрабатывать инструкцию после следующей, 
поэтому \ac{PC} указывает туда. Этот факт нужно запомнить.

Если $a=0$, тогда к \ac{PC} ничего не будет прибавлено и 
в \ac{PC} запишется актуальный на тот момент \ac{PC} (который больше на 8) 
и произойдет переход на метку \IT{loc\_180}. 
Это на 8 байт дальше места, где находится инструкция \TT{ADDCC}.

Если $a=1$, тогда в \ac{PC} запишется 
$PC+8+a*4 = PC+8+1*4 = PC+12 = 0x184$. Это адрес метки \IT{loc\_184}.

При каждой добавленной к $a$ единице итоговый \ac{PC} увеличивается на 4.

4 это длина инструкции в режиме ARM и одновременно с этим, 
длина каждой инструкции \TT{B}, их здесь следует 5 в ряд.

Каждая из этих пяти инструкций \TT{B} передает управление дальше, где собственно и происходит то, 
что запрограммировано в операторе \IT{switch()}.
Там происходит загрузка указателя на свою строку, итд.

\subsubsection{ARM: \OptimizingKeilVI (\ThumbMode)}

\lstinputlisting[caption=\OptimizingKeilVI (\ThumbMode),style=customasmARM]{patterns/08_switch/2_lot/lot_ARM_thumb_O3.asm}

\myindex{ARM!\ThumbMode}
\myindex{ARM!\ThumbTwoMode}
В режимах Thumb и Thumb-2 уже нельзя надеяться на то, что все инструкции имеют одну длину.

Можно даже сказать, что в этих режимах инструкции переменной длины, как в x86.

\myindex{jumptable}
Так что здесь добавляется специальная таблица, содержащая информацию о том, как много вариантов здесь,
не включая варианта по умолчанию, и смещения, для каждого варианта. Каждое смещение кодирует метку, куда нужно передать
управление в соответствующем случае.

\myindex{ARM!Переключение режимов}
\myindex{ARM!\Instructions!BX}
Для того чтобы работать с таблицей и совершить переход, вызывается служебная функция

\IT{\_\_ARM\_common\_switch8\_thumb}. 
Она начинается с инструкции \TT{BX PC}, чья функция~--- переключить процессор в ARM-режим.

Далее функция, работающая с таблицей. 
Она слишком сложная для рассмотрения в данном месте, так что пропустим это.

% TODO explain it...

\myindex{ARM!\Registers!Link Register}
Но можно отметить, что эта функция использует регистр \ac{LR} как указатель на таблицу.

Действительно, после вызова этой функции, в \ac{LR} был записан адрес после инструкции

\TT{BL \_\_ARM\_common\_switch8\_thumb}, а там как раз и начинается таблица.

Ещё можно отметить, что код для этого выделен в отдельную функцию для того, 
чтобы не нужно было каждый раз генерировать 
точно такой же фрагмент кода для каждого выражения switch().

\IDA распознала эту служебную функцию и таблицу автоматически дописала комментарии к меткам вроде \\
\TT{jumptable 000000FA case 0}.

